#include "Sequence.hxx"
#include "Project.hxx"
#include "VideoController.hxx"
#include "TrackingThread.hxx"


VideoController::VideoController(QObject *parent) : QObject(parent)
{
	_project = nullptr;
	_view = nullptr;
	_videoThread = nullptr;
	_trackingThread = nullptr;
}

VideoController::~VideoController()
{
	if (_videoThread)
	{
		while (_videoThread->isRunning())
		{
			_videoThread->stop();
		}

		delete _videoThread;
		_videoThread = 0;
	}

	if (_trackingThread)
	{
		while (_trackingThread->isRunning())
		{
			_trackingThread->stop();
		}

		delete _trackingThread;
		_trackingThread = 0;
	}
}


void VideoController::seekVideoPosition(double pos)
{
	if (_project && _project->getActiveSequence())
		_project->getActiveSequence()->seekVideoPosition(pos);
}

void VideoController::pauseVideo()
{
	if (_trackingThread && _trackingThread->isRunning())
		_trackingThread->pause();
}

void VideoController::resumeVideo()
{
	if (_trackingThread && _trackingThread->isRunning())
		_trackingThread->resume();

	if (_videoThread && _videoThread->isRunning())
		_videoThread->resume();
}

void VideoController::startTrack(const char* trackerType)
{
	if (_project && _project->getActiveSequence())
		_project->getActiveSequence()->prepareTrackingObjects();
	_trackingThread->setTrackerType(trackerType);
	_trackingThread->startTrack();
}

void VideoController::makeSingleFrameObjects()
{
	if (_project && _project->getActiveSequence())
	{
		_project->getActiveSequence()->makeSingleFrameObjects();
	}
}

void VideoController::makeNegativeSampleFrame()
{
	if (_project && _project->getActiveSequence())
	{
		_project->getActiveSequence()->makeNegativeSampleFrame();
	}
}

void VideoController::stopTrack()
{
	_trackingThread->stopTrack();
	if (_project && _project->getActiveSequence())
	{
		_project->getActiveSequence()->moveTrackedObjects();
	}
}

void VideoController::playVideo()
{
	if (!_project) return;
	
	if (!_project->getActiveSequence()) return;

	Sequence* sequence = _project->getActiveSequence();

	if (_videoThread)
	{
		if (_videoThread->isRunning())
		{
			_videoThread->stop();

			while (_videoThread->isRunning())
			{
				_videoThread->wait(200);
				_videoThread->stop();
			}
		}

		delete _videoThread;
		_videoThread = 0;
	}

	if (_trackingThread)
	{
		while (_trackingThread->isRunning())
		{
			_trackingThread->stop();
		}

		delete _trackingThread;
		_trackingThread = 0;
	}

	_videoThread = new VideoThread();
	_videoThread->setFramePool(sequence->getFramePool());
	_videoThread->setVideoModel(sequence);
	_videoThread->initialize();
	_videoThread->start();

    _trackingThread = new YOLOTrackingThread();
	_trackingThread->setModel(sequence);
	_trackingThread->setInputFramePool(sequence->getFramePool());
	_trackingThread->setOutputFramePool(sequence->getTrackedFramePool());
	_trackingThread->initialize();
	_trackingThread->start();
}

void VideoController::slow()
{
	if (_trackingThread && _trackingThread->isRunning())
		_trackingThread->slow();
}

void VideoController::fast()
{
	if (_trackingThread && _trackingThread->isRunning())
		_trackingThread->fast();
}

void VideoController::nextFrame()
{
	if (_videoThread && _videoThread->isRunning())
		_videoThread->resume();

	if (_trackingThread && _trackingThread->isRunning())
		_trackingThread->next();
}

void VideoController::actionGoFrame(int findex)
{
	if (_videoThread && _videoThread->isRunning())
		_videoThread->actionGoFrame(findex);
}
